﻿#include "GLLInc.h"
#include "GLLOSApp.h"
#include "GLLGameApp.h"
#include "GLLTheSystem.h"


//-----------------------------------------------------------------------------
#ifdef GLL_WIN

namespace GLL
{
	const DWORD dwStyle = WS_OVERLAPPEDWINDOW-WS_MAXIMIZEBOX-WS_SIZEBOX;

	LRESULT CALLBACK StateWndProc(HWND hWnd, uint message, WPARAM wParam, LPARAM lParam)
	{
		switch(message)
		{
		case WM_CLOSE:
			theApp()->Shutdown();
			break;
		}
		return ::DefWindowProc(hWnd, message, wParam, lParam);
	}

	Size2Di OSApp::GetScreenSize_spec()
	{
		return Size2Di(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
	}

	Size2Di OSApp::GetOSWindowPos_spec()
	{
		RECT rect;
		GetWindowRect(_hWnd, &rect);
		return Size2Di(rect.left, rect.top);
	}

	HINSTANCE OSApp::RegisterOSWindowClass()
	{
		HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(0);
		WNDCLASSEXA wcex;
		wcex.cbSize = sizeof(WNDCLASSEX); 
		wcex.style			= CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc	= (WNDPROC)StateWndProc;
		wcex.cbClsExtra		= 0;
		wcex.cbWndExtra		= 0;
		wcex.hInstance		= hInstance;
		wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)107);
		wcex.hIconSm		= LoadIcon(hInstance, (LPCTSTR)108);
		wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
		wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
		wcex.lpszMenuName	= 0;// (LPCTSTR)IDC_GAME;
		wcex.lpszClassName	= _GetClassName();
		ATOM atom = RegisterClassExA(&wcex);
		if(!atom)
		{
			DWORD err = GetLastError();
			err;
			return 0;
		}
		return hInstance;
	}

	void OSApp::CreateOSWindow_spec( )
	{
		Size2Di size = GetWindowInitialSize();
		_hInstance = RegisterOSWindowClass();
		if(!_hInstance) GLL_Throw("Registering Window Failed");
		_hWnd = CreateWindowA(_GetClassName(), "", dwStyle, 0, 0, size.width, size.height, NULL, NULL, _hInstance, NULL);
		if (!_hWnd) GLL_Throw("Creating Window Failed");
		MoveOSWindow(size);
		//BOOL uni = IsWindowUnicode(GetHWND());
	}

	void OSApp::OnClientSizeChanged_spec(const Size2Di&)
	{

	}

	void OSApp::MoveOSWindow_spec(const Area2Di& a)
	{
		::MoveWindow(_hWnd, a.left, a.top, a.width, a.height, true);
	}

	void OSApp::ShowOSWindow_spec()
	{
		if(!GetHWND()) return;
		ShowWindow(GetHWND(), TRUE);
		UpdateWindow(GetHWND());
	}

	void OSApp::DoSetClientSize_spec( const Size2Di& s)
	{
		Size2Di size(s);
		Size2Di scr_size = GetScreenSize_spec();
		//桌面分辨率小于目标分辨率
		if( scr_size.width <= size.width || scr_size.height <= size.height )
		{
			size = GetClientSizeFromFrameSize(scr_size);
		}

		Size2Di pos = GetOSWindowPos_spec();
		MoveOSWindow_spec(Area2Di(pos.width, pos.height, size.width, size.height));
	}

	Size2Di OSApp::GetClientSize_spec()
	{
		if(!GetHWND()) return Size2Di();
		RECT clientRect;
		GetClientRect(GetHWND(), &clientRect);
		Size2Di size(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);
		return size;
	}

	Size2Di OSApp::GetFrameSizeFromClientSize_spec( const Size2Di& size )
	{
		RECT rcWork;
		SetRect(&rcWork, 0, 0, size.width, size.height);
		AdjustWindowRect(&rcWork, dwStyle, FALSE);
		int width = rcWork.right-rcWork.left;
		int height = rcWork.bottom-rcWork.top;
		Size2Di ret(width, height);
		return ret;
	}

	void OSApp::SetOSAppTitle_spec( StringStream& in )
	{
		String title(in.str());
		SetWindowTextA(GetHWND(), title.c_str());
	}

	void OSApp::DrawOSAppBkPicture_spec()
	{
		if(!_startBkgnd) return;

		HDC hdc = GetDC(GetHWND());
		HDC hMemDC = CreateCompatibleDC(hdc);
		SelectObject(hMemDC, _startBkgnd); 
		RECT rect;
		GetClientRect(GetHWND(), &rect);

		BITMAP bitmap;
		::GetObject(_startBkgnd, sizeof(BITMAP), &bitmap);

		//BitBlt(hdc, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY);
		int iOldMode = SetStretchBltMode(hdc, COLORONCOLOR); 
		StretchBlt(hdc, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY); 
		SetStretchBltMode(hdc, iOldMode); 

		DeleteDC(hMemDC);
		ReleaseDC(GetHWND(), hdc);
	}

	void OSApp::LoadBkPicture_spec()
	{
		_startBkgnd = (HBITMAP)LoadImageA((HINSTANCE)GetModuleHandle(0), "Pack\\UI\\BkGnd.bmp", 
			IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
		//gStartUpBkGnd = LoadBitmap((HINSTANCE)GetModuleHandle(0), (LPCTSTR)IDB_STARTUP);
	}

	void OSApp::UnloadBkPicture_spec()
	{
		if (_startBkgnd)
		{
			::DeleteObject(_startBkgnd);
			_startBkgnd =0;
		}
	}

	void OSApp::ProcOSMessage_spec()
	{
		MSG  msg;
		while( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
	}

	void OSApp::SetThisThreadPriority( ThreadPriority tp )
	{
		int wtp = THREAD_PRIORITY_NORMAL;

		switch(tp)
		{
		case TP_NORMAL: wtp = THREAD_PRIORITY_NORMAL; break;
		case TP_LOW: wtp = THREAD_PRIORITY_BELOW_NORMAL; break;
		case TP_HIGHT: wtp = THREAD_PRIORITY_ABOVE_NORMAL; break;
		case TP_LOWEST: wtp = THREAD_PRIORITY_LOWEST; break;
		case TP_HIGHEST: wtp = THREAD_PRIORITY_HIGHEST; break;
		}

		BOOL ret = SetThreadPriority(GetCurrentThread(), wtp);
		if(!ret){
			GLL_LOG("ERROR: SetThisThreadPriority(%d) failed", tp);
		}

	}

};//GLL

#endif GLL_WIN
